home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Control Common / DllEntry.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  8.7 KB  |  491 lines  |  [TEXT/CWIE]

  1. //
  2. //  DLLENTRY.CPP
  3. //
  4. //  Copyright (C) Microsoft Corporation, 1996
  5. //
  6.  
  7. #include <stdio.h>
  8. #include "ocHeaders.h"
  9. #include "CBaseControl.h"
  10. #include "ResourceMap.h"
  11. #include "dllentry.h"
  12.  
  13. #define INITGUID
  14. #include <initguid.h>
  15.  
  16. #include "register.h"    
  17.  
  18. typedef struct
  19. {
  20.     CFragInitBlock        InitBlock;
  21.     ResourceMapHandle    TopMapHdl;
  22.     unsigned long        RefThisDll;    //    used to be g_cRefThisDll = 0;
  23.     Boolean                Inited;
  24.     short                ResRefNum;
  25. }
  26. dlldata;
  27.  
  28. static dlldata    DllData;
  29.  
  30. static pascal void WriteToOleReg (char * strKey, char * strValue);
  31. static char *        privstrcat(char * dest, const char * src);
  32.  
  33. enum 
  34. {
  35.     uppDllInitRoutineProcInfo = kPascalStackBased
  36.          | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  37.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(CFragInitBlockPtr)))
  38. };
  39.  
  40. ProcInfoType __procinfo = uppDllInitRoutineProcInfo;
  41.  
  42.  
  43. extern "C" 
  44. {
  45. OSErr pascal __initialize(CFragInitBlockPtr initBlkPtr);
  46. OSErr pascal DllInitializationRoutine(CFragInitBlockPtr initBlkPtr);
  47. OSErr pascal DllExecutionRoutine(CFragInitBlockPtr initBlkPtr);
  48. void pascal DllTerminationRoutine(CFragInitBlockPtr initBlkPtr);
  49. }
  50.  
  51.  
  52. short    GetDllResRefNum(void)
  53. {
  54.     return DllData.ResRefNum;
  55. }
  56.  
  57. ResourceMapHandle GetDllTopMapHdl(void)
  58. {
  59.     return DllData.TopMapHdl;
  60. }
  61.  
  62.  
  63. //
  64. //  Class Factory
  65. //
  66. //  Class for creating an instance of the control class
  67. //
  68.  
  69. class CClassFactory:
  70.     public IClassFactory
  71. {
  72. public:
  73.     //  *** Constructor/Destructor methods ***
  74.     CClassFactory(void);
  75.     ~CClassFactory(void);
  76.  
  77.     //  *** IUnknown methods ***
  78.     STDMETHOD(QueryInterface)(REFIID riid, void** ppv);
  79.     STDMETHOD_(ULONG, AddRef)(void);
  80.     STDMETHOD_(ULONG, Release)(void);
  81.  
  82.     //  *** IClassFactory methods ***
  83.     STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void**
  84.         ppvObject);
  85.     STDMETHOD(LockServer)(unsigned long fLock);
  86.  
  87. protected:
  88.     ULONG m_cRef;
  89.  
  90. };
  91.  
  92.  
  93. //
  94. //  CBaseClassFactory::CClassFactory
  95. //
  96. //  Constructor
  97. //
  98.  
  99. CClassFactory::CClassFactory()
  100. {
  101.     m_cRef = 1;
  102.     DLLAddRef();
  103.     
  104.     if (!DllData.Inited && DllData.InitBlock.fragLocator.where == kDataForkCFragLocator)
  105.     {
  106.         short    InResFile = ::CurResFile();
  107.         ResourceMapHandle    InTopMapHdl = ResourceMapHandle( ::LMGetTopMapHndl() );
  108.  
  109.         DllData.Inited = true;
  110.         //    open up the resource fork of the dll and save it off
  111.         DllData.ResRefNum = ::FSpOpenResFile(DllData.InitBlock.fragLocator.u.onDisk.fileSpec, fsRdPerm);
  112.         DllData.TopMapHdl = ResourceMapHandle( ::LMGetTopMapHndl() );
  113.         ::UseResFile(InResFile);
  114.         ::LMSetTopMapHndl( Handle(InTopMapHdl) );
  115.     }
  116. }
  117.  
  118. //
  119. //  CClassFactory::~CClassFactory
  120. //
  121. //  Destructor
  122. //
  123.  
  124. CClassFactory::~CClassFactory()
  125. {
  126.     if (DllData.Inited)
  127.     {
  128.         if (DllData.TopMapHdl != NULL)
  129.             ::LMSetTopMapHndl( Handle(DllData.TopMapHdl) );
  130.  
  131.         if (DllData.ResRefNum != -1)
  132.         {
  133.             ::FSClose(DllData.ResRefNum);
  134.             DllData.ResRefNum = -1;
  135.         }
  136.     }
  137.     DLLRelease();
  138. }
  139.  
  140. //
  141. //  CClassFactory::IUnknown::QueryInterface
  142. //
  143. //  Returns a pointer to the specified interface on a component to which a
  144. //  client currently holds an interface pointer.
  145. //
  146.  
  147. STDMETHODIMP
  148. CClassFactory::QueryInterface(REFIID riid, void** ppv)
  149. {
  150.     HRESULT rc = 0;
  151.     
  152.     void* pv;
  153.  
  154.     if (riid == IID_IUnknown || riid == IID_IClassFactory)
  155.         pv = (void*)(LPCLASSFACTORY) this;
  156.     else {
  157.         *ppv = NULL;
  158.         rc = E_NOINTERFACE;
  159.         goto Done;
  160.     }
  161.  
  162.     *ppv = pv;
  163.     ((LPUNKNOWN) pv)->AddRef();
  164.     rc =  S_OK;
  165.  
  166. Done:
  167.     return rc;
  168. }
  169.  
  170. //
  171. //  CClassFactory::IUnknown::AddRef
  172. //
  173. //  Increments the reference count for the calling interface.
  174. //
  175.  
  176. STDMETHODIMP_(ULONG)
  177. CClassFactory::AddRef(void)
  178. {
  179.     return ++m_cRef;
  180. }
  181.  
  182. //
  183. //  CClassFactory::IUnknown::Release
  184. //
  185. //  Decrements the reference count for the calling interface on a object.  If
  186. //  the reference count on the object falls to zero, the object is freed.
  187. //
  188.  
  189. STDMETHODIMP_(ULONG)
  190. CClassFactory::Release(void)
  191. {
  192.     if (--m_cRef != 0)
  193.         return m_cRef;
  194.  
  195.     delete this;
  196.     return 0;
  197. }
  198.  
  199. //
  200. //  CClassFactory::IClassFactory::Release
  201. //
  202. //  Decrements the reference count for the calling interface on a object.  If
  203. //  the reference count on the object falls to zero, the object is freed.
  204. //
  205.  
  206. STDMETHODIMP
  207. CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObject)
  208. {
  209. #pragma unused (pUnkOuter)
  210.     HRESULT     hr;
  211.     CControl*     pControl;
  212.     
  213.     pControl = new CControl();
  214.  
  215.     if (pControl == NULL) 
  216.     {
  217.         *ppvObject = NULL;
  218.         return E_OUTOFMEMORY;
  219.     }
  220.  
  221.     hr = pControl->QueryInterface(riid, ppvObject);
  222.     ((IControl*)pControl)->Release();
  223.     
  224.     return hr;
  225. }
  226.  
  227. //
  228. //  CClassFactory::IClassFactory::LockServer
  229. //
  230. //  Decrements the reference count for the calling interface on a object.  If
  231. //  the reference count on the object falls to zero, the object is freed.
  232. //
  233.  
  234. STDMETHODIMP
  235. CClassFactory::LockServer(unsigned long fLock)
  236. {
  237. #pragma unused (fLock)
  238.     return E_NOTIMPL;
  239. }
  240.  
  241. #pragma export on
  242.  
  243. //
  244. //  DllGetClassObject
  245. //
  246. //  Called by COM to create the class factory
  247. //
  248.  
  249. STDAPI
  250. DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
  251. {
  252.  
  253.  
  254.     HRESULT         hr;
  255.     CClassFactory*     pcf;    
  256.  
  257.     *ppv = NULL;
  258.  
  259.     if (IsEqualCLSID(rclsid, CLSID_ocx)) 
  260.     {
  261.         pcf = new CClassFactory();
  262.         if (pcf != NULL) 
  263.         {
  264.             hr = pcf->QueryInterface(riid, ppv);
  265.             pcf->Release();
  266.         } 
  267.         else 
  268.         {
  269.             hr = E_OUTOFMEMORY;
  270.         }
  271.     } 
  272.     else 
  273.     {
  274.         hr = CLASS_E_CLASSNOTAVAILABLE;
  275.     }
  276.  
  277.     return hr;
  278. }
  279.  
  280.  
  281. //
  282. //  DllCanUnloadNow
  283. //
  284. //  Determines whether the dll can be unloaded yet
  285. //
  286.  
  287. STDAPI
  288. DllCanUnloadNow(void)
  289. {
  290.     return (DllData.RefThisDll == 0) ? S_OK : S_FALSE;
  291. }
  292.  
  293. #define    kCLSIDConst            "CLSID\\"
  294. #define    kINPROCSERVERConst    "\\InprocServer"
  295. #define    kALIASConst            "\\Alias"
  296. #define    kALS2Const            "ALS2:"
  297.  
  298. STDAPI
  299. DllRegisterServer(void)
  300. {
  301.     HKEY        hKey;
  302.     char        Key[256];
  303.     char        DataValue[256];
  304.     SCODE         sc;
  305.     unsigned long    AliasLength;
  306.  
  307.     DllUnregisterServer();
  308.     Key[0] = '\0';
  309.     privstrcat(Key, kCLSIDConst kOCXCLSID);
  310.     if (RegOpenKey(HKEY_CLASSES_ROOT, Key, &hKey) == S_OK) 
  311.         RegCloseKey(hKey);
  312.     else
  313.     {
  314.         AliasHandle    AliasH;
  315.         HKEY        hkey = NULL;
  316.  
  317.         WriteToOleReg(Key, kOCXFullUserTypeName);
  318.  
  319.         Key[0] = '\0';
  320.         privstrcat(Key, kCLSIDConst kOCXCLSID kINPROCSERVERConst);
  321.         DataValue[0] = '\0';
  322.         privstrcat(DataValue, kALS2Const kOCXProgID);
  323.  
  324.         WriteToOleReg(Key, DataValue);
  325.  
  326.         ::NewAlias (NULL, DllData.InitBlock.fragLocator.u.onDisk.fileSpec, &AliasH);
  327.  
  328.         if((AliasH) && (RegOpenKey(HKEY_CLASSES_ROOT, Key, &hkey) == ERROR_SUCCESS))
  329.         {
  330.             AliasLength = ::GetHandleSize(Handle(AliasH));
  331.             
  332.             Key[0] = '\0';
  333.             privstrcat(Key, kCLSIDConst kOCXCLSID kINPROCSERVERConst kALIASConst);
  334.  
  335.             sc = RegSetValueEx(hkey, "Alias", 0, REG_BINARY, 
  336.                 (char*)*AliasH, AliasLength);
  337.                 
  338.             RegCloseKey(hkey);
  339.         }
  340.  
  341.         if (AliasH)
  342.             ::DisposeHandle( Handle(AliasH) );
  343.     }
  344.  
  345.     return S_OK;
  346. }
  347.  
  348. //
  349. //  DllUnregisterServer
  350. //
  351. //  Unregisters the server from the COM registry
  352. //
  353.  
  354. STDAPI
  355. DllUnregisterServer(void)
  356. {
  357.     HKEY        hKey;
  358.     char        DataValue[256];
  359.     char        SubKey[256];
  360.     long        length;
  361.  
  362.     if (RegOpenKey(HKEY_CLASSES_ROOT, "CLSID", &hKey) == S_OK)
  363.     {
  364.         SubKey[0] = '\0';
  365.         privstrcat(SubKey, kCLSIDConst kOCXCLSID);
  366.         if (RegQueryValue(HKEY_CLASSES_ROOT, SubKey, DataValue, &length) == S_OK)
  367.         {
  368.             RegDeleteKey(HKEY_CLASSES_ROOT, SubKey);
  369.         }
  370.  
  371.         RegCloseKey(hKey);
  372.     }
  373.  
  374.     return S_OK;
  375. }
  376.  
  377.  
  378. //
  379. //  DllInitializationRoutine
  380. //
  381. //  Initialization routine called by COM
  382. //
  383.  
  384. OSErr pascal
  385. DllInitializationRoutine(CFragInitBlockPtr initBlkPtr)
  386. {
  387.     DllData.InitBlock = *initBlkPtr;
  388.     DllData.TopMapHdl = NULL;
  389.     DllData.Inited = false;
  390.     DllData.ResRefNum = -1;
  391.     DllData.RefThisDll = 0;
  392.  
  393.     __initialize(initBlkPtr);
  394.     return noErr;
  395. }
  396.  
  397.  
  398. //
  399. //  DllInitializationRoutine
  400. //
  401. //  Initialization routine called by COM
  402. //
  403.  
  404. OSErr pascal
  405. DllExecutionRoutine(CFragInitBlockPtr initBlkPtr)
  406. {
  407. #pragma unused (initBlkPtr)
  408.     //    this routine isn't getting called by anybody
  409.     return noErr;
  410. }
  411.  
  412.  
  413. //
  414. //  DllTerminationRoutine
  415. //
  416. //  Termination routine called by COM
  417. //
  418.  
  419. void pascal
  420. DllTerminationRoutine(CFragInitBlockPtr initBlkPtr)
  421. {
  422. #pragma unused (initBlkPtr)
  423. }
  424.  
  425.  
  426. //
  427. //  WriteToOleReg
  428. //
  429. //  Utility function for writing a CLASSID key to the COM registry
  430. //
  431.  
  432. pascal void WriteToOleReg (char * strKey, char * strValue)
  433. {
  434.     static Boolean     fNoErr = true;
  435.     SCODE             sc;
  436.  
  437.     sc = RegSetValue(HKEY_CLASSES_ROOT, strKey, REG_SZ, strValue, 0);
  438.     if (sc != S_OK)
  439.     {
  440.         fNoErr = false;
  441.     }
  442. }
  443.  
  444.  
  445. //
  446. //  privstrcat
  447. //
  448. //  Utility function for concatenating strings
  449. //
  450.  
  451. char * privstrcat(char * dst, const char * src)
  452. {
  453. #if !__POWERPC__
  454.     
  455.     const    char * p = src;
  456.                 char * q = dst;
  457.     
  458.     while (*q++);
  459.     
  460.     q--;
  461.     
  462.     while (*q++ = *p++);
  463.     
  464. #else
  465.     
  466.     const    unsigned char * p = (unsigned char *) src - 1;
  467.                 unsigned char * q = (unsigned char *) dst - 1;
  468.     
  469.     while (*++q) ;
  470.     
  471.     q--;
  472.     
  473.     while ((*++q = *++p) != 0) ;
  474.  
  475. #endif
  476.     
  477.     return(dst);
  478. }
  479.  
  480. unsigned long DLLAddRef()
  481. {
  482.     return ++DllData.RefThisDll;
  483. }
  484.  
  485. unsigned long DLLRelease()
  486. {
  487.     return --DllData.RefThisDll;
  488. }
  489.  
  490. #pragma export off
  491.